﻿using System;
using System.Collections.Generic;
using System.Text;

namespace BCCommon
{
    public static class StringUtils
    {
        internal enum SnakeCaseState
        {
            Start,
            Lower,
            Upper,
            NewWord
        }

        public static string ToSnakeCase(this string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return s;
            }

            StringBuilder sb = new StringBuilder();
            SnakeCaseState state = SnakeCaseState.Start;

            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == ' ')
                {
                    if (state != SnakeCaseState.Start)
                    {
                        state = SnakeCaseState.NewWord;
                    }
                }
                else if (char.IsUpper(s[i]))
                {
                    switch (state)
                    {
                        case SnakeCaseState.Upper:
                            bool hasNext = (i + 1 < s.Length);
                            if (i > 0 && hasNext)
                            {
                                char nextChar = s[i + 1];
                                if (!char.IsUpper(nextChar) && nextChar != '_')
                                {
                                    sb.Append('_');
                                }
                            }
                            break;
                        case SnakeCaseState.Lower:
                        case SnakeCaseState.NewWord:
                            sb.Append('_');
                            break;
                    }

                    sb.Append(char.ToLowerInvariant(s[i]));
                    state = SnakeCaseState.Upper;
                }
                else if (s[i] == '_')
                {
                    sb.Append('_');
                    state = SnakeCaseState.Start;
                }
                else
                {
                    if (state == SnakeCaseState.NewWord)
                    {
                        sb.Append('_');
                    }

                    sb.Append(s[i]);
                    state = SnakeCaseState.Lower;
                }
            }

            return sb.ToString();
        }

        public static string ToCamelCase(this string s)
        {
            if (string.IsNullOrWhiteSpace(s))
            {
                return s;
            }
            s = s.Trim();
            StringBuilder sb = new StringBuilder();
            SnakeCaseState state = SnakeCaseState.Start;
            int i = 0;
            while (i < s.Length)
            {
                if (s[i] == ' ')
                {
                    sb.Append(s[i]);
                    state = SnakeCaseState.NewWord;
                }
                else if (s[i] == '_')
                {
                    state = SnakeCaseState.NewWord;
                }
                else if (char.IsLower(s[i]))
                {
                    if (state == SnakeCaseState.Start || state == SnakeCaseState.NewWord)
                    {
                        sb.Append(char.ToUpper(s[i]));
                        state = SnakeCaseState.Lower;
                    }
                    else if (state == SnakeCaseState.Lower)
                    {
                        sb.Append(s[i]);
                    }
                }
                else
                {
                    sb.Append(s[i]);
                    state = SnakeCaseState.Lower;
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 转全角。
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <remarks>
        /// 全角空格为12288，半角空格为32，其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
        /// </remarks>
        public static string ToSBC(this string input)
        {
            // 半角转全角：
            char[] c = input.ToCharArray();
            for (int i = 0; i < c.Length; i++)
            {
                if (c[i] == 32)
                {
                    c[i] = (char)12288;
                    continue;
                }
                if (c[i] < 127)
                    c[i] = (char)(c[i] + 65248);
            }
            return new string(c);
        }

        /// <summary>
        /// 转半角。
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <remarks>
        /// 全角空格为12288，半角空格为32，其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
        /// </remarks>
        public static string ToDBC(this string input)
        {
            char[] c = input.ToCharArray();
            for (int i = 0; i < c.Length; i++)
            {
                if (c[i] == 12288)
                {
                    c[i] = (char)32;
                    continue;
                }
                if (c[i] > 65280 && c[i] < 65375)
                    c[i] = (char)(c[i] - 65248);
            }
            return new string(c);
        }

        /// <summary>
        /// 模板字符串替换。
        /// </summary>
        /// <param name="templateString"></param>
        /// <param name="value"></param>
        /// <param name="replaceNullToWhiteSpace"></param>
        /// <returns></returns>
        public static string Format(this string templateString, object value, bool replaceNullToWhiteSpace = true)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (string.IsNullOrWhiteSpace(templateString))
            {
                return templateString;
            }

            var sb = new StringBuilder(templateString);

            foreach (var parameter in value.GetType().GetProperties())
            {
                string key = string.Format("{{{0}}}", parameter.Name);
                object val = parameter.GetValue(value);

                if (!replaceNullToWhiteSpace && val == null)
                {
                    continue;
                }

                sb.Replace(key, val != null ? val.ToString() : string.Empty);
            }

            return sb.ToString();
        }


        public static string BankCardWithSpecialChar(string cardNo)
        {

            string left = cardNo.Substring(0, 4);
            string right = cardNo.Substring(cardNo.Length - 4);
            return left + " **** **** " + right;
        }
    }
}
